package com.cheetah.protocol.codec;

import com.cheetah.exceptions.CheetahException;
import com.cheetah.protocol.RequestHeader;
import com.cheetah.protocol.Heartbeat;
import com.cheetah.protocol.Request;
import com.cheetah.protostuff.ProtostuffSerialization;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

import static com.cheetah.constants.AttributeKeyConstants.*;
import static com.cheetah.constants.ProtocolConstants.*;

@Slf4j
public class CheetahDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

        in.markReaderIndex();

        if (in.readableBytes() < 0) {
            return;
        }

        if (!in.isReadable()) {
            return;
        }

        if (in.readableBytes() < PROTOCOL_MAGIC_LEN) {
            return;
        }


        short magic = in.readShort();

        switch (magic) {
            case PROTOCOL_MAGIC_PROTO: //protobuf 魔数

                //魔数已经读取过，这里减掉魔数所占长度
                if (in.readableBytes() < PROTOCOL_HEAD_LENGTH - PROTOCOL_MAGIC_LEN) {
                    return;
                }
                short version = in.readShort();
                byte[] typeBytes = new byte[4];
                in.readBytes(typeBytes);
                String type = new String(typeBytes);
                short flag = in.readShort();

                Request request = processData(in);
                if (request != null) {
                    out.add(request);
                }

                ctx.channel().attr(AttributeKey.valueOf(ATTRIBUTE_KEY_MAGIC)).set(magic);
                ctx.channel().attr(AttributeKey.valueOf(ATTRIBUTE_KEY_TYPE)).set(type);
                ctx.channel().attr(AttributeKey.valueOf(ATTRIBUTE_KEY_FLAG)).set(flag);
                break;

            case PROTOCOL_MAGIC_HEARTBEAT: //heartbeat 魔数

                if (in.readableBytes() < 4) {
                    return;
                }

                byte[] bytes = new byte[4];
                in.readBytes(bytes);
                Heartbeat heartbeat = Heartbeat.builder()
                        .cmd(new String(bytes))
                        .build();
                out.add(heartbeat);

                break;

            default:
                throw new CheetahException("protocol is invalid!");
        }
    }

    private Request processData(ByteBuf in) {

//        int headLen = in.readInt();
        int bodyLen = in.readInt();
//        if(in.readableBytes() < headLen + bodyLen){
        if(in.readableBytes() < bodyLen){
            in.resetReaderIndex();
            return null;
        }else {
            Request request = Request.builder()
                    .build();
//            byte[] head = new byte[headLen];
            byte[] body = new byte[bodyLen];
//            in.readBytes(head);
            in.readBytes(body);

//            RequestHeader requestHeader = ProtostuffSerialization.deserialize(head, RequestHeader.class);
//            request.setRequestHeader(requestHeader);
            request.setBody(body);
            return request;
        }
    }
}
